package org.ccay.manage.enumerable.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;

import org.ccay.core.base.BatchVO;
import org.ccay.core.base.KeyValuePairVO;
import org.ccay.core.base.PageVO;
import org.ccay.core.base.PagedResult;
import org.ccay.core.base.RamPager;
import org.ccay.core.request.Application;
import org.ccay.core.util.StringUtil;
import org.ccay.enumerable.DefaultEnumHelp;
import org.ccay.enumerable.EnumItem;
import org.ccay.enumerable.PlainEnumItem;
import org.ccay.enumerable.SourceEnum;
import org.ccay.manage.enumerable.dao.IDBEnumManageDao;
import org.ccay.manage.enumerable.service.IDBEnumManageService;
import org.ccay.manage.enumerable.vo.EnumItemVO;
import org.ccay.security.util.SecurityUtil;

@Named("dbEnumManageService")
public class DBEnumManageService implements IDBEnumManageService {

	@Inject
	@Named("enums")
	DefaultEnumHelp defaultEnumHelp;
	
	@Inject
	IDBEnumManageDao dbEnumManageDao;
	
	
	@Override
	public PagedResult<EnumItemVO> findPagedEnums(EnumItemVO condition, PageVO page) {
		//获取所有
		List<EnumItem> all = defaultEnumHelp.getAll();
		//数据库枚举类型
		List<EnumItemVO> dbEnums = dbEnumManageDao.findAll();
		//新的枚举集合
		List<EnumItemVO> allItemVO = new ArrayList<EnumItemVO>();
		//将数据合并
		for(EnumItem item: all){
			//条件筛选
			if(!StringUtil.isNullOrEmpty(condition.getType())){
				if(!item.getType().toUpperCase().contains(condition.getType().toUpperCase())){
					continue;
				}
			}
			if(!StringUtil.isNullOrEmpty(condition.getName())){
				if(!item.getName().toUpperCase().contains(condition.getName().toUpperCase())){
					continue;
				}
			}
			if(!StringUtil.isNullOrEmpty(condition.getValue())){
				if(!item.getValue().toUpperCase().contains(condition.getValue().toUpperCase())){
					continue;
				}
			}
			if(!StringUtil.isNullOrEmpty(condition.getDisplayValue())){
				if(!item.getDisplayValue().toUpperCase().contains(condition.getDisplayValue().toUpperCase())){
					continue;
				}
			}
			if(condition.getIndex() >= 0){
				if(item.getIndex() != condition.getIndex()){
					continue;
				}
			}
			if(!StringUtil.isNullOrEmpty(condition.getSource())){
				if(!item.getSource().equals(condition.getSource())){
					continue;
				}
			}
			
			//类型转换放入新集合
			EnumItemVO enumItemVO = new EnumItemVO(item,null);
			allItemVO.add(enumItemVO);
			enumItemVO.setVirtualId(item.getType()+"|"+item.getValue());
			//合并描述
			if(enumItemVO.getSource().equals(SourceEnum.SOURCE_DB.getValue())){
				for(EnumItemVO dbItem : dbEnums){
					if(enumItemVO.equals(dbItem)){
						enumItemVO.setDescription(dbItem.getDescription());
						break;
					}
				}
			}
		}
		
		//内存分页
		page.setTotalRows(allItemVO.size());
		PagedResult<EnumItemVO> result = new PagedResult<EnumItemVO>();
		result.setPageVO(page);
		if(!allItemVO.isEmpty()){
			RamPager<EnumItemVO> ramPager = new RamPager<EnumItemVO>(allItemVO,page.getPageSize());
			result.setResult(ramPager.page(page.getCurPage()));
		}else{
			result.setResult(Collections.<EnumItemVO> emptyList());
		}
		return result;
	}

	@Override
	public void batchOperation(BatchVO<EnumItemVO> batchItems) {
		Map<String, Object> validateInfo = validateForBatch(batchItems);
		if(!validateInfo.isEmpty()){
			return;
		}
		if(!batchItems.getItems2Delete().isEmpty()){
			SecurityUtil.checkPermission("enumManagement:delete");
			dbEnumManageDao.deleteEnumItems(batchItems.getItems2Delete());
		}
		if(!batchItems.getItems2Create().isEmpty()){
			SecurityUtil.checkPermission("enumManagement:create");
			dbEnumManageDao.createEnumItems(batchItems.getItems2Create());
		}
		if(!batchItems.getItems2Update().isEmpty()){
			SecurityUtil.checkPermission("enumManagement:update");
			dbEnumManageDao.updateEnumItems(batchItems.getItems2Update());
		}
		defaultEnumHelp.refresh();
	}

	@Override
	public int updateEnumItems(List<EnumItemVO> items2Update) {
		int effective = dbEnumManageDao.updateEnumItems(items2Update);
		defaultEnumHelp.refresh();
		return effective;
	}

	@Override
	public int createEnumItems(List<EnumItemVO> items2Create) {
		int effective = dbEnumManageDao.createEnumItems(items2Create);
		defaultEnumHelp.refresh();
		return effective;
	}

	@Override
	public int deleteEnumItems(List<EnumItemVO> items2Delete) {
		int effective = dbEnumManageDao.deleteEnumItems(items2Delete);
		defaultEnumHelp.refresh();
		return effective;
	}

	@Override
	public Map<String, Object> validateForBatch(BatchVO<EnumItemVO> batchItems) {
		//模拟最终结果集
		List<EnumItem> newAll = new ArrayList<EnumItem>();
		//遍历去除将更新及要删除的数据
		for(EnumItem item : defaultEnumHelp.getAll()){
			boolean isFind = false;
			for(EnumItemVO toUpdateAndDelete : batchItems.getUpdateAndDeleteUnion()){
				if(toUpdateAndDelete.getVirtualId().equals(item.getType()+"|"+item.getValue())){
					isFind = true;
					break;
				}
			}
			if(!isFind){
				newAll.add(item);
			}
		}
		//加入将插入及将更新的数据
		for(EnumItemVO toCreateAndUpdate : batchItems.getCreateAndUpdateUnion()){
			newAll.add(new PlainEnumItem(
					toCreateAndUpdate.getType(),
					toCreateAndUpdate.getName(),
					toCreateAndUpdate.getValue(),
					toCreateAndUpdate.getDisplayValue(), 
					toCreateAndUpdate.getIndex(), 
					SourceEnum.SOURCE_DB.getValue()));
		}
		//校验重复
		Map<String,Object> errorInfo = new HashMap<String,Object>();
		//一、校验提供的新增及修改的枚举项是否本身重复
		Set<String> typevalues = new HashSet<String>();//1、类、值唯一
		Set<String> typeindexs = new HashSet<String>();//2、类、序号唯一
		for(EnumItem row : newAll){
			//1、类、值 唯一
			String typevaluekey = row.getType()+"|"+row.getValue();
			if(typevalues.contains(typevaluekey)){
				getSetInMap(errorInfo,"TypeValueUniqueFail",String.class).add(typevaluekey);
			}else{
				typevalues.add(typevaluekey);
			}
			//2、类、序号唯一
			String typeindexkey = row.getType()+"|"+row.getIndex();
			if(typeindexs.contains(typeindexkey)){
				getSetInMap(errorInfo,"TypeIndexUniqueFail",String.class).add(typeindexkey);
			}else{
				typeindexs.add(typeindexkey);
			}
		}
		return errorInfo;
	}
	
	@SuppressWarnings("unchecked")
	private <T> Set<T> getSetInMap(Map<String,Object> map, String type,Class<T> T){
		Set<T> set = (Set<T>)map.get(type);
		if(set == null){
			set = new HashSet<T>();
			map.put(type, set);
		}
		return set;
	}

	@Override
	public List<KeyValuePairVO> findAllEnumType() {
		List<KeyValuePairVO> result = new ArrayList<KeyValuePairVO>();
		for(String type:defaultEnumHelp.getEnumContainer().keySet()){
			result.add(new KeyValuePairVO(type,type));
		}
		Collections.sort(result,new Comparator<KeyValuePairVO>(){
			@Override
			public int compare(KeyValuePairVO o1, KeyValuePairVO o2) {
				return o1.getKey().compareTo(o2.getKey());
			}});
		return result;
	}

	@Override
	public void reloadAll() {
		//开发环境不校验权限
		if(Application.getCurrent().getEnviorment().equals(Application.DEV)){
			defaultEnumHelp.refresh();
		}else{
			SecurityUtil.checkPermission("enumManagement:reload");
			defaultEnumHelp.refresh();
		}
	}
}
